package person.bangbang.im.Androidgin.Loopback;

import java.util.List;

import person.bangbang.im.Androidgin.Framework.Account;
import person.bangbang.im.Androidgin.Framework.Accounts;
import person.bangbang.im.Androidgin.Framework.Buddies;
import person.bangbang.im.Androidgin.Framework.Buddy;
import person.bangbang.im.Androidgin.Framework.Conversations;
import person.bangbang.im.Androidgin.Framework.Message;
import person.bangbang.im.Androidgin.Framework.Protocol;
import person.bangbang.im.Androidgin.Framework.StatusType;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;

/**
 * JUST a example loopback protocol IMPL.
 * if you add a new protocol, you can get useful 
 * info HERE.
 * 
 * @author bangbang.song@gmail
 *
 */
public class LoopbackProtocol extends Protocol{
	private static final String TAG = "LoopbackProtocol";
	
	public static final int CODE_LOGIN_STEP = 1;
	
	private boolean mHasLogin = false;
	
	private Handler mMainHandler = null;
	private Handler mImHandler;
	private Handler mLoginHandler;
	
    private int mCurrStep = 0;
    private final int TOTAL_STEPS = 2;
    
    private Account mAcc = null;
    private Accounts mAccs = Accounts.getInstance();
    private Buddies mBuddies = Buddies.getInstance();
    private Conversations mChats = Conversations.getInstance();
    
    private Buddy mMyself, mLoopbacker;
	
	public LoopbackProtocol(String userName, String passward, StatusType type) {
		super(userName, passward, type);
		mMainHandler = new Handler();
		mImHandler = new ImHandler(this);
		mLoginHandler = new LoginHandler();
	}
	

	public void perfomRcvdIm(String userId, String msg) {
		Buddy from = mBuddies.findBuddyById(userId);
		if (null != from) {
			mChats.getOrNewConversation(from).doImRcvd(new Message(from, mMyself, msg));
		} else {
			Log.d(TAG,"Rcvd a msg from a buddy who are not exist. ohh^^^\nuserId : " + userId);
		}
	}
	public void perfomSendIm(String userId, String msg) {
		Buddy from = mBuddies.findBuddyById(userId);
		if (null != from) {
			mChats.getOrNewConversation(from).doImRcvd(new Message(from, mMyself, msg));
		} else {
			Log.d(TAG, "a msg has been sentto buddy who are not exist. ohh^^^");
		}
	}
	
	private int getCurrentStep(){
		synchronized(this) {
			return mCurrStep;
		}
	}
	private void incCurrentStep(){
		synchronized(this) {
			mCurrStep++;
		}
	}
	
	@Override
	public String getProtocolID() {
		// TODO Auto-generated method stub
		return "loopback";
	}

	@Override
	public boolean sendIm(Message msg) {
		// TODO Auto-generated method stub
		mChats.getOrNewConversation(msg.getTo()).doImSend(msg);
//		mChats.getOrNewChat(msg.getTo()).onImRcvd(new Message(msg.getTo(), 
//				                                          msg.getFrom(), 
//				                                          msg.getMessage()
//				                                          )
//		                                      );
		ImThread t = new ImThread(this, mImHandler);
		t.start();
		return false;
	}

	@Override
	public boolean signoff() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean signon() {
		// TODO Auto-generated method stub
		mAcc = mAccs.findAccount(getProtocolID(), mUserName);
		if (null == mAcc) {
			throw (new RuntimeException("Can't get the account i have attached!!!"));
		}
		
		// just two
		mMyself = new Buddy(getProtocolID() + ':' + mUserName, "me[" + mUserName + "]", mAcc);
//		mMyself = new Buddy(getProtocolID() + ':' + "me", "me[bangbang.Song]", mAcc);
		mLoopbacker = new Buddy(getProtocolID() + ':' + mUserName + ':' + "loopbacker", "loopbacker", mAcc);
		mBuddies.add(mMyself);
		mBuddies.add(mLoopbacker);
		
		// all code in framework run in main UI thread.
		// if your service is going to do CPU intensive 
		// or blocking operations, do it in another Thread.
		mLoginThread.start();
		
//		int i = 0;
//		while (i < 40) {
//			if (mHasLogin) return true;
//			try{
//				Thread.sleep(500);
//			} catch (InterruptedException e) {
//				e.printStackTrace();
//			}
//			i++;
//		}
		return false;
	}
	
	private void dispathLoginStep(){
		int i = getCurrentStep();
		if (i == TOTAL_STEPS) 
			mHasLogin = true;
		
		dispatchLoginStep(i+1, TOTAL_STEPS, "login..("+ String.valueOf(i+1) + '/' + TOTAL_STEPS + ')');

	}
	private Thread mLoginThread = new Thread(new Runnable(){
		// TODO producer/consumer pattern.
		public void run() {
			// TODO Auto-generated method stub

						for (int i = 1 ; i <= TOTAL_STEPS ; i++) {
							try {
								Thread.sleep(3*1000);
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
							
							// not order guard.
//								mMainHandler.post(new Runnable() {
//									public void run() {
//										// TODO Auto-generated method stub
//										dispathLoginStep();
//									}
//								});
							android.os.Message msg = android.os.Message.obtain();
							msg.what = CODE_LOGIN_STEP;
							msg.obj = new String("login..");
							
							Bundle b = new Bundle();
							b.putInt("step", i);
							b.putInt("totoal_steps", TOTAL_STEPS);
							msg.setData(b);
							
//							mLoginHandler.sendMessageDelayed(msg, 1*1000);
							mLoginHandler.sendMessage(msg);
						}
					}
	     });
	
	private class LoginHandler extends Handler {
		@Override
		public void handleMessage(android.os.Message msg) {
			// TODO Auto-generated method stub
			switch (msg.what) {
			case CODE_LOGIN_STEP:
				Log.d(TAG, "Rcvd a message : " + msg);
				String str = (String) msg.obj;
//				Bundle b = msg.getData();
				Bundle b = msg.peekData();
				int step = b.getInt("step");
				int total = b.getInt("totoal_steps");
				dispatchLoginStep(step, total, str);
				break;

			default:
				
				Log.d(TAG, "Rcvd a message i can not understand : " + msg);
				break;
			}
		}
	}

	@Override
	public Buddy getMyself() {
		// TODO Auto-generated method stub
		return mMyself;
	}
}
